package zhou.chs.p4_10;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

public class MainActivity extends AppCompatActivity {
    //声明控件
    private TextView tvRxd;     //数据显示区，显示接收与发送数据
    private TextView myIP;      //显示本机IP地址
    private TextView listIP;    //显示已接入客户端IP地址
    //声明变量
    Hashtable mtable;   //哈希表，保存已接入客户端IP地址和Socket
    OutputStream out;   //输出数据流
    ServerSocket server;    //服务端Socket
    accept_client accept_thread; //服务端监听线程
    RecThread rt;
    private Handler mHandler;   //消息线程
    String ip;  //IP地址
    boolean accept_flag = false;
    String strmsg;  //数据显示字符串
    byte[] reg = new byte[256]; //服务端数据区
    byte[] rxd = new byte[256]; //Socket接收到的数据
    String ipl; //客户端IP地址列表
    int tn;  //报文计数，超过10条信息清信息区
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实例化控件
        tvRxd = (TextView) findViewById(R.id.idtv1);
        myIP = (TextView)findViewById(R.id.idtv2);
        listIP = (TextView)findViewById(R.id.idtv3);
        //数据显示区可滚动
        tvRxd.setMovementMethod(ScrollingMovementMethod.getInstance());
        mtable=new Hashtable();
        ip = getIpAddressString();  //获取本机IP
        myIP.setText("本机IP:"+ip+"  绑定端口：8080");
        for(int i=0;i<256;i++) reg[i]=(byte)(i&0xFF);   //初始化服务端数据区
        mHandler = new MyHandler();     //实例化Handler，用于进程间的通信
        try {
            server = new ServerSocket(8080,32);  //绑定监听的端口号,最多32个客户端
        } catch (SocketException ee) {
            ee.printStackTrace();
            return;
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        accept_thread = new accept_client();    //创建线程等待客户端的连接
        accept_flag = true;
        accept_thread.start();
    }
    //在主线程处理Handler传回来的message
    class MyHandler extends Handler {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:     //有新客户端接入
                    ipl="已接入IP：\n";
                    //遍历哈希表中的IP地址
                    for(Iterator<String> iterator = mtable.keySet().iterator(); iterator.hasNext();){
                        String key=iterator.next();
                        ipl+=key+"\n";
                    }
                    listIP.setText(ipl);    //显示已接入客户端IP地址
                    break;
                case 2:     //收到新数据
                    tn++;
                    if(tn>10){
                        tn=0;
                        strmsg="";
                    }
                    String s = (String)msg.obj;
                    String[] split = s.split(":");
                    s = split[0];  //分解出IP地址
                    int n = Integer.parseInt(split[1]); //分解出收到数据字节数
                    String s2="";
                    //以16进制显示收到数据
                    for(int i=0;i<n;i++) s2=s2+String.format("%02X", rxd[i])+" ";
                    strmsg = strmsg + "from " + s + ":  " + s2 + "\n";
                    try {
                        Socket ss = (Socket) mtable.get(s);
                        out = ss.getOutputStream();     //获取客户端对应的socket并建立数据流
                        byte [] txd = new byte[256];    //发送缓冲区
                        if(rxd[7]==(byte) 0x03){
                            int btn = rxd[11]<<1;
                            int adn = rxd[9];
                            for (int i=0;i<8;i++) txd[i]=rxd[i];
                            txd[5]=(byte)(btn+3);
                            txd[8]=(byte)btn;
                            for (int i=0;i<btn;i++) txd[i+9]=reg[i+adn];
                            out.write(txd,0,btn+9);   //写发送缓冲区
                            s2="";
                            //以16进制显示发送数据
                            for(int i=0;i<btn+9;i++) s2=s2+String.format("%02X", txd[i])+" ";
                            strmsg = strmsg + "to " + s + ":  " + s2 + "\n";
                        }
                        if(rxd[7]==(byte) 0x10){
                            for (int i=0;i<12;i++) txd[i]=rxd[i];
                            txd[5]=6;
                            out.write(txd,0,12);   //写发送缓冲区
                            s2="";
                            //以16进制显示发送数据
                            for(int i=0;i<12;i++) s2=s2+String.format("%02X", txd[i])+" ";
                            strmsg = strmsg + "to " + s + ":  " + s2 + "\n";
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    tvRxd.setText(strmsg);
                    break;
            }
        }
    }
    //获取本机IP
    public static String getIpAddressString() {
        try {
            for (Enumeration<NetworkInterface> enNetI = NetworkInterface
                    .getNetworkInterfaces(); enNetI.hasMoreElements(); ) {
                NetworkInterface netI = enNetI.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = netI
                        .getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
                        return inetAddress.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return "";
    }
    //按钮单击事件响应
    public void clear(View view){
        strmsg="";
        tvRxd.setText("");  //接收区清空
    }
    //服务器监听客户端发来的链接请求
    private class accept_client extends Thread
    {
        @Override
        public void run() {
            try {
                while (accept_flag)    //允许监听
                {
                    if(server.isClosed()){
                        return;     //如ServerSocket关闭则退出
                    }
                    Socket socket = server.accept();  //有客户端接入
                    String s = socket.getInetAddress().getHostAddress(); //客户端IP地址
                    Socket ss = (Socket) mtable.get(s);
                    if(ss!=null) mtable.remove(s);  //如果列表已有该IP，移除
                    mtable.put(s,socket);  //新的客户端加入列表
                    Message msg = new Message();
                    msg.what=1;
                    mHandler.sendMessage(msg);
                    rt = new RecThread(socket);
                    rt.start();  //启动新客户端数据接收线程
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            super.run();
        }
    }
    // TCP服务器数据接收线程
    private class RecThread extends Thread {
        private final Socket mmSocket;
        private final InputStream mmInStream;
        public RecThread(Socket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            try {
                tmpIn = mmSocket.getInputStream();      //数据通道创建
            } catch (IOException e) { }
            mmInStream = tmpIn;
        }
        public final void run() {
            while (!mmSocket.isClosed()) {
                byte[] b = new byte[512];
                try {
                    int cnt = mmInStream.read(b);   //检查是否接收到数据
                    InetAddress address = mmSocket.getInetAddress();
                    if(cnt>0) {
                        for(int i=0;i<cnt;i++) rxd[i]=b[i];
                        Message msg = new Message();
                        msg.what = 2;
                        //消息内容含发送数据的IP地址和数据字节数
                        msg.obj = address.getHostAddress() + ":" + cnt;
                        mHandler.sendMessage(msg);
                        try{
                            sleep(100);
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                    }
                } catch (NullPointerException e) {
                    e.printStackTrace();
                    break;
                } catch (IOException e) {
                    break;
                }
            }
        }
        public void cancel() {      //关闭连接
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }
    @Override   //程序退出前关闭Socket
    protected void onDestroy() {
        super.onDestroy();
        rt.cancel();
    }
}
